package com.xjk.encryp;

import java.nio.charset.StandardCharsets;

/**
 * @author xjk
 * @date 2024-11-12
 */
public class Base64Util {
  private static final char[] BASE64CODE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
  private static final int[] BASE64DECODE = new int[128];

  static {
    for (int i = 0; i < BASE64DECODE.length; i++) {
      BASE64DECODE[i] = -1;
    }
    for (int i = 0; i < BASE64CODE.length; i++) {
      BASE64DECODE[BASE64CODE[i]] = i;
    }
  }

  private Base64Util() {
  }

  public static String encode(byte[] data) {
    StringBuilder sb = new StringBuilder((data.length + 2) / 3 * 4);
    int i = 0;
    while (i < data.length) {
      int b0 = data[i++] & 0xff;
      sb.append(BASE64CODE[b0 >> 2]);
      if (i == data.length) {
        sb.append(BASE64CODE[(b0 & 0x03) << 4]);
        sb.append("==");
        break;
      }
      int b1 = data[i++] & 0xff;
      sb.append(BASE64CODE[((b0 & 0x03) << 4) | (b1 >> 4)]);
      if (i == data.length) {
        sb.append(BASE64CODE[(b1 & 0x0f) << 2]);
        sb.append("=");
        break;
      }
      int b2 = data[i++] & 0xff;
      sb.append(BASE64CODE[((b1 & 0x0f) << 2) | (b2 >> 6)]);
      sb.append(BASE64CODE[b2 & 0x3f]);
    }
    return sb.toString();
  }

  public static byte[] decode(String base64) {
    int padding = 0;
    for (int i = base64.length() - 1; i >= 0 && base64.charAt(i) == '='; i--) {
      padding++;
    }
    int len = (base64.length() * 3) / 4 - padding;
    byte[] result = new byte[len];
    int j = 0;
    for (int i = 0; i < base64.length(); i += 4) {
      int b0 = BASE64DECODE[base64.charAt(i)];
      int b1 = BASE64DECODE[base64.charAt(i + 1)];
      result[j++] = (byte) ((b0 << 2) | (b1 >> 4));
      if (j < len) {
        int b2 = BASE64DECODE[base64.charAt(i + 2)];
        result[j++] = (byte) ((b1 << 4) | (b2 >> 2));
        if (j < len) {
          int b3 = BASE64DECODE[base64.charAt(i + 3)];
          result[j++] = (byte) ((b2 << 6) | b3);
        }
      }
    }
    return result;
  }

  public static String base64Encode(String str) {
    return encode(str.getBytes(StandardCharsets.UTF_8));
  }

  public static byte[] decryBASE64(String key) {
    return decode(key);
  }

  public static String encryptBASE64(byte[] key) {
    return encode(key);
  }
}
